package com.coolw.test.prefix;

import com.alibaba.fastjson.JSON;
import com.coolw.test.prefix.annotation.PrefixClass;
import com.coolw.test.prefix.annotation.PrefixField;
import com.coolw.test.prefix.util.PrefixUtil;
import org.dromara.hutool.core.text.StrUtil;

import java.lang.reflect.Field;

/**
 * Main
 *
 * @author coolw
 * @date 2024/5/23 9:29
 */
public class Main {

    public static void main(String[] args) throws IllegalAccessException {
        D d = new D();

        C c = new C();
        c.setD(d);

        B b = new B();
        b.setC(c);

        A a = new A();
        a.setB(b);

        boolean isRequest = false;
        if (isRequest) {
            d.setDId("ddddd");
            c.setCId("ccccc");
            b.setBId("bbbbb");
            a.setAId("aaaaa");
        } else {
            d.setDId("LXJ_ddddd");
            c.setCId("LXJ_ccccc");
            b.setBId("LXJ_bbbbb");
            a.setAId("LXJ_aaaaa");
        }

        Main main = new Main();
        // request
        if (isRequest) {
            main.requestPreHandle(a);
            System.out.println("request:" + a);
        } else {
            // response
            A resp = main.outputPostHandle(JSON.toJSONString(a), A.class);
            System.out.println("response:" + resp);
        }
    }

    /**
     * 我方上送给机构的请求数据,字段值前缀添加
     *
     * @param request 请求数据
     * @param <T>     数据类型
     */
    private <T> void requestPreHandle(T request) throws IllegalAccessException {
        if (request == null) {
            return;
        }

        // 需要处理数据前缀类标识
        PrefixClass prefixClass = request.getClass().getAnnotation(PrefixClass.class);
        if (prefixClass == null) {
            return;
        }

        // 字段数据前缀处理,添加前缀
        fieldPrefixHandle(request, true);
    }

    /**
     * 对机构返回数据 output 解析及字段值前缀去除
     *
     * @param output 机构返回的业务数据 json 字符串
     * @param clazz  业务数据class
     * @param <R>    业务数据类型
     * @return 业务数据对象
     */
    private <R> R outputPostHandle(String output, Class<R> clazz) throws IllegalAccessException {
        if (output == null || clazz == null) {
            return null;
        }

        R result = JSON.parseObject(output, clazz);
        if (result == null) {
            return null;
        }

        // 需要处理数据前缀类标识
        PrefixClass prefixClass = result.getClass().getAnnotation(PrefixClass.class);
        if (prefixClass == null) {
            return result;
        }

        // 字段数据前缀处理,去除前缀
        fieldPrefixHandle(result, false);
        return result;
    }

    /**
     * 字段数据前缀处理
     *
     * @param obj       数据对象
     * @param isRequest 如果为 true 代表我方调用机构接口的请求数据(添加前缀),反之为机构返回的数据(去除前缀)
     * @param <T>       数据类型
     */
    private <T> void fieldPrefixHandle(T obj, boolean isRequest) throws IllegalAccessException {
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            Class<?> fieldType = field.getType();

            // 如果为基本数据类型,则跳过
            if (fieldType.isPrimitive()) {
                continue;
            }

            // 如果为 String 类型,直接处理
            if (fieldType.equals(String.class)) {
                // 如果该字段没有注解 PrefixField,则跳过
                PrefixField prefixField = field.getAnnotation(PrefixField.class);
                if (prefixField == null) {
                    continue;
                }

                String strVal = (String) field.get(obj);
                if (StrUtil.isBlank(strVal)) {
                    continue;
                }

                if (isRequest) {
                    field.set(obj, PrefixUtil.setValue(strVal));
                } else {
                    field.set(obj, PrefixUtil.getValue(strVal));
                }
            } else {
                // 如果为对象,递归处理(如果有其他类型,如Map,Array等,请自行扩展)
                Object fieldValue = field.get(obj);
                if (fieldValue != null) {
                    // 需要处理数据前缀类标识
                    PrefixClass prefixClass = fieldValue.getClass().getAnnotation(PrefixClass.class);
                    if (prefixClass != null) {
                        fieldPrefixHandle(fieldValue, isRequest);
                    }
                }
            }
        }
    }
}
